﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using CommonFramework;
using CommonFramework.Log;
using CommonFramework.Serialize.BytesArray;
using Net.Channel;
using Net.Client;
using Net.Server;
using Delegate = CommonFramework.Event.Delegate;

namespace Net
{
    public class NetSession
    {
        public Socket Socket { get;protected set; }
        public NetChannel Channel { get; private set; }
        public NetManagerBase NetManager { get; private set; }

        //心跳包的收发时间点
        public long LastHeartPingTime;
        public long LastHreatPongTime;

        //对端的地址和端口
        private string _remoteHost=null;
        private int _remotePort=0;
        private void TryCheckRemote()
        {
            if (string.IsNullOrEmpty(_remoteHost) && IsConnected())
                NetUtil.FromEndPoint(Socket.RemoteEndPoint, ref _remoteHost, ref _remotePort);
        }
        public string RemoteHost
        {
            get
            {
                TryCheckRemote();
                return _remoteHost;
            }
        }
        public int RemotePort
        {
            get
            {
                TryCheckRemote();
                return _remotePort;
            }
        }

        public NetSession(Socket socket,NetManagerBase manager,
            Delegate.Param1WithRet<NetSession,NetChannel> channelProvider)
        {
            this.Socket = socket;
            this.NetManager = manager;
            this.Channel=channelProvider.Invoke(this);
        }

        public bool IsConnected() => Channel.IsConnected();
        public bool IsConnecting() => Channel.IsConnecting();
        public bool IsClosed() => Channel.IsClosed();

        /// <summary>
        /// 只关闭管理的Socket,
        ///     如果是客户端使用 NetClientManager.Close()
        ///     如果是服务端使用 NetServerManager.CloseClient()
        /// </summary>
        public void Close()
        {
            if (IsClosed())
                return;

            Channel?.Close();

            Socket?.Close();
            Socket = null;
        }
        public void Clear()
        {
            LastHeartPingTime = 0;
            LastHreatPongTime = 0;

            _remoteHost = null;
            _remotePort = 0;

            Channel?.Clear();
        }

        public void Send(byte[] bytes, int offset, int length) => Channel.Send(bytes, offset, length);
        public void Send(NetPacket packet) => Channel.Send(packet);
        public void Send(BytesBuffer sendBytes) => Channel.Send(sendBytes);

        public void Receive(byte[] bytes, int offset, int length) => Channel.Receive(bytes, offset, length);
        public void Receive(NetPacket packet) => Channel.Receive(packet);
    }
}